//场景漫游
import { transformCartesianToWGS84 } from "../plotCommon.ts";
export default class SceneRoaming {
  //static properties
  static algoithm_type = {
    linear: Cesium.LinearApproximation, //线性插值
    lagrangePolynomial: Cesium.LagrangePolynomialApproximation, //拉格朗日插值
    hermitePolynomial: Cesium.HermitePolynomialApproximation, //艾尔米特多项式近似插值
  };

  //properties
  _viewer;
  _height;
  _trackEntity; //漫游时的相机视角跟随Entity对象Cesium.Entity
  _positions; //坐标序列Array<Cartesian3>
  _sampledPositionProperty; //路径采样对象
  _sampledOrientationProperty; //angle
  //插值类型-3种[LagrangePolynomialApproximation;LinearApproximation;HermitePolynomialApproximation]
  _interpolationAlgorithm;
  _speed; //漫游速度
  _startTime; //漫游开始时间
  _endTime; //漫游结束时间
  _timeInterval; //路径采样时间间隔
  _completeCallBack; //路径漫游结束时的回调函数
  _following; //是否开启相机跟随
//   _clockListen; //监听器
  _onTickEvent
  /**
   * 设置漫游速度
   * @param {Number} value 速度值>0
   */
  set speed(value) {
    if (typeof value === "number" && value > 0) this._speed = value;
  }

  /**
   * 设置路径插值方式
   * @param {string} value 静态属性algoithm_type的key值,可选值:{linear,lagrangePolynomial,hermitePolynomial}
   */
  set interpolationAlgorithm(value) {
    SceneRoaming.algoithm_type[value] &&
      (this._interpolationAlgorithm = SceneRoaming.algoithm_type[value]);
  }

  //构造器
  /**
   *
   * @param {Cesium.Viewer} viewer Cesium视景器对象
   * @param {Array<Cesium.Cartesian3>} positions 路径漫游的节点数组
   * @param {Number} speed timeline时间动画播放速度<=>控制场景漫游时的移动速度,默认为1.0
   * @param {Object} options 其它配置项
   *                  {Cesium.InterpolationAlgorithm} interpolationAlgorithm 路径漫游时的插值模型,默认为线性插值
   *                  {Number} timeInterval 路径的采样时间间隔,默认为30s
   *                  {String} startIOSDate 开始时间,ISO时间字符串,默认为1970-01-01 00:00:00
   *                  {Boolean} autoDestroy 是否在路径漫游结束后自动销毁,默认true-是
   */
  constructor(viewer, positions, speed = 1.0, options = {}) {
    const {
      interpolationAlgorithm = SceneRoaming.algoithm_type.linear,
      timeInterval = 30,
      startIosDate = "1970-01-01 08:00:00",
      autoDestory = true,
      height = 1000,
    } = options || {};
    if (!Cesium.defined(viewer))
      throw new Error(`The viewer param should not be undefined or null!`);
    if (!Array.isArray(positions) || positions.length === 0)
      throw new Error(`The path vertexes for roaming is empty or illegal`);
    this._options = options;
    this._viewer = viewer;
    this._positions = positions;
    this._speed = speed;
    //   this.height=height
    this._sampledPositionProperty = new Cesium.SampledPositionProperty();
    this._sampledOrientationProperty = new Cesium.SampledPositionProperty();
    const LagrangePolynomialApproximation =
      Cesium.LagrangePolynomialApproximation;

    this._sampledOrientationProperty.setInterpolationOptions({
      interpolationAlgorithm: interpolationAlgorithm, //插值方式
      interpolationDegree: 0, //插值度
    });
    this._sampledPositionProperty.setInterpolationOptions({
      interpolationAlgorithm: interpolationAlgorithm, //插值方式
      interpolationDegree: 1, //插值度
    });
    this._timeInterval = timeInterval;
    const isoDate = new Date(startIosDate).toISOString();
    this._startTime = Cesium.JulianDate.fromIso8601(
      isoDate,
      new Cesium.JulianDate()
    );
    this._endTime = Cesium.JulianDate.addSeconds(
      this._startTime,
      (this._positions.length - 1) * this._timeInterval,
      new Cesium.JulianDate()
    );
    console.log(this._positions, Cesium.JulianDate.fromIso8601(isoDate));
    console.log(isoDate, this._startTime, this._endTime);
  }

  //methods
  doWhenComplete(tick) {
    //触发时间停止函数
    console.log(`clock stop`, tick);
    console.log(this._completeCallBack);
    this._completeCallBack(tick);
    //其它设置
    this.destroyRoaming();
  }

  /**
   * 监听时间线-在飞行结束时执行某些任务
   * @param {*} callback 回调函数
   */
  monitorTimelineTick(callback = () => {}) {
    // this._viewer.clock.onTick.addEventListener((tick) => {
    //   // console.log('click tick', tick)
    //   // if(Cesium.JulianDate.equals(this._endTime,tick.currentTime)) console.log("增加到结束时间");
    // })
    this._viewer.clock.onStop.addEventListener(this.doWhenComplete, this);
  }

  /**
   * 调整Julian时间因子
   * @param {Cesium.JulianDate} startJulianTime 路径漫游的起始虚拟时间
   * @param {Cesium.JulianDate} endJulianTime 路径漫游的结束虚拟时间
   * @param {Number} speed 漫游时的时间行进速度
   * @param {Boolean} isBound clock是否存在边界,默认有边界
   */
  setJulianDateFactor(
    startJulianTime,
    endJulianTime,
    speed = 1.0,
    isBound = true
  ) {
    this._viewer.clock.startTime = startJulianTime;
    this._viewer.clock.stopTime = endJulianTime;
    //将当前时间设置为起始时间
    this._viewer.clock.currentTime = startJulianTime.clone();
    if (isBound) this._viewer.clock.clockRange = Cesium.ClockRange.CLAMPED;
    else this._viewer.clock.clockRange = Cesium.ClockRange.UNBOUNDED;
    //调整timeline组件的时间区间到startTime~endTime范围
    if (this._viewer.timeline) {
      this._viewer.timeline.zoomTo(startJulianTime, endJulianTime);
    }
    //   this._viewer.timeline.zoomTo(startJulianTime, endJulianTime)
    this._viewer.clock.multiplier = speed;
    console.log("时间调整结束");
  }

  /**
   * 位置采样
   * @param {Array<Cesium.Cartesian3>} positions
   */
  samplePositions(positions) {
    const { _startTime, _timeInterval } = this;
    positions.forEach((position, index) => {
      const currentTime = Cesium.JulianDate.addSeconds(
        _startTime,
        index * _timeInterval,
        new Cesium.JulianDate()
      );
      this._sampledPositionProperty.addSample(currentTime, position);
    });
    console.log(this._sampledPositionProperty, "采样结束");
  }
  // 角度采样
  sampleOrientations(positions) {
    const { _startTime, _timeInterval } = this;
    this.calculateOrientation(positions).forEach((orientation, index) => {
      console.log(orientation, "orientation");
      const currentTime = Cesium.JulianDate.addSeconds(
        _startTime,
        index * _timeInterval,
        new Cesium.JulianDate()
      );
      this._sampledOrientationProperty.addSample(currentTime, orientation);
    });
    console.log(this._sampledOrientationProperty, "方向采样结束");
  }
  calculateOrientation(positions) {
    let orientations = [];

    for (let i = 0; i < positions.length; i++) {
      const prevIndex = Math.max(i - 1, 0);
      const nextIndex = Math.min(i + 1, positions.length - 1);

      const prevPosition = positions[prevIndex];
      const currentPosition = positions[i];
      const nextPosition = positions[nextIndex];

      const heading1 = Math.atan2(
        currentPosition.y - prevPosition.y,
        currentPosition.x - prevPosition.x
      );
      const heading2 = Math.atan2(
        nextPosition.y - currentPosition.y,
        nextPosition.x - currentPosition.x
      );
      const angle = heading2 - heading1;
      console.log(angle, "angle");
      const heading = Cesium.Math.toRadians(angle); // 相机的航向角（heading），这里设为0度，即朝向正北方向
      const pitch = Cesium.Math.toRadians(0); // 相机的俯仰角（pitch），这里设为-90度，即向下看
      const roll = Cesium.Math.toRadians(0); // 相机的翻滚角（roll），这里设为0度
      orientations.push({
        x: angle,
        y: 0,
        z: 0,
      });
      //   orientations.push(angle)
    }

    return orientations;
  }

  // 示例使用

  /**
   * 启动漫游
   * @param {Boolean} showPath 是否显示路径
   * @param {Object} options 配置项
   *                     width:路径宽度
   *                     material:路径材质
   *                     modelUrl:模型url
   */
  startRoaming(showPath = true, options = {}) {
    const {
      width = 3, //路径宽度
      material = Cesium.Color.RED.withAlpha(0.5), //路径材质
      modelUrl = "http://127.0.0.1/tiles/air/Cesium_Air.glb", //模型路径
      following = true, //是否跟随模型移动,默认是
      height,
      show,
      afterCallback = () => {}, //路径漫游时执行某些任务
    } = options || {};
    console.log(options);
    this._height = height;
    this.destroyRoaming(); //先清除上一次漫游
    //开启新一次的漫游
    this._viewer.clock.multiplier = this._speed;
    this._completeCallBack = afterCallback;
    this._following = following;
    this.setJulianDateFactor(this._startTime, this._endTime, this._speed, true);
    this.monitorTimelineTick();
    this.samplePositions(this._positions); //路径采样
    this.sampleOrientations(this._positions);
    if (showPath) {
      this._trackEntity = this._viewer.entities.add({
        position: this._sampledPositionProperty,
        availability: new Cesium.TimeIntervalCollection([
          new Cesium.TimeInterval({
            start: this._startTime,
            stop: this._endTime,
          }),
        ]),
        model: { uri: modelUrl }, //跟随模型
        show:false,
        point: {
          pixelSize: 15,
          color: Cesium.Color.ORANGE,
        },
        path: new Cesium.PathGraphics({ width: width, material: material }), //显示路径
        orientation: new Cesium.VelocityOrientationProperty(
          this._sampledPositionProperty
        ),
      });
      let $this=this
      this._viewer.clock.shouldAnimate = true; //开启动画
      this._onTickEvent = this._viewer.clock.onTick.addEventListener(function(){
              let viewer=$this._viewer
      if (viewer.clock.shouldAnimate === true) {
          let ori = $this._trackEntity.orientation.getValue(viewer.clock.currentTime); 
          let center = $this._trackEntity.position.getValue(viewer.clock.currentTime);
          center.z= center.z+$this._height
          var mtx3 = Cesium.Matrix3.fromQuaternion(ori);
          var mtx4 = Cesium.Matrix4.fromRotationTranslation(mtx3, center);
          var hpr = Cesium.Transforms.fixedFrameToHeadingPitchRoll(mtx4);
          const headingTemp = hpr.heading;
          const pitchTemp = hpr.pitch;
          const heading = Cesium.Math.toRadians(Cesium.Math.toDegrees(headingTemp) + 90);
          const pitch = Cesium.Math.toRadians(Cesium.Math.toDegrees(pitchTemp) - 12);
          const range = 140.0;
          viewer.camera.lookAt(center, new Cesium.HeadingPitchRange(heading, pitch, range));
      }
      });
      !!this._following && (this._viewer.trackedEntity = this._trackEntity); //模型跟随
    } else {
    //   this._viewer.clock.startTime = this._startTime;
    //   this._viewer.clock.stopTime = this._endTime;
    //   this._viewer.clock.currentTime = this._startTime;
    //   this._viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; // 循环播放漫游动画
    //   let $this = this;
    //   this._viewer.clock.multiplier = this._speed;
    //   this._clockListen = this._viewer.clock.onTick.addEventListener(function (
    //     clock
    //   ) {
    //     const time = clock.currentTime;
    //     const position = $this._sampledPositionProperty.getValue(time);
    //     const deltaTime = 0.1; // 前一段时间的长度（以秒为单位）
    //     // 计算前0.1秒的时间
    //     const timeBefore = Cesium.JulianDate.addSeconds(
    //       time,
    //       deltaTime,
    //       new Cesium.JulianDate()
    //     );
    //     const positionBefore =
    //       $this._sampledPositionProperty.getValue(timeBefore);
    //     let a = $this.calcAngle(position, positionBefore);
    //     if (position) position.z = position.z + $this._height;
    //     if (Cesium.defined(position)) {
    //       // 根据旋转矩阵设置相机的方向
    //       $this._viewer.scene.camera.setView({
    //         destination: position,
    //         orientation: a,
    //       });
    //     }
    //   });
    //   this._viewer.clock.shouldAnimate = true; //开启动画
    //   !!this._following && (this._viewer.trackedEntity = this._trackEntity); //模型跟随
    }
 
  }
 

  /**
   * 暂停路径漫游
   */
  pauseRoaming() {
    this._viewer.clock.shouldAnimate = false;
    this._viewer.trackedEntity = null;
  }
  calcAngle(p, b) {
    if (!p || !b) return;
    const {
      Cartesian3,
      Transforms,
      Math: CesiumMath,
      Quaternion,
      Matrix3,
    } = Cesium;
    const point1 = p; // 第一个点的笛卡尔坐标系
    const point2 = b; // 第二个点的笛卡尔坐标系
    // 计算从第一个点到第二个点的方向
    const direction = Cartesian3.subtract(point1, point2, new Cartesian3());
    Cartesian3.normalize(direction, direction);
    // 检查方向向量是否有效
    if (isNaN(direction.x) || isNaN(direction.y) || isNaN(direction.z)) {
      throw new Error("Failed to calculate direction");
    }
    // // 计算从第一个点到第二个点的方向的heading和pitch
    const heading = Cesium.Math.toDegrees(Math.atan2(direction.y, direction.x));
    const pitch = Cesium.Math.toDegrees(
      Math.asin(direction.z / Cesium.Cartesian3.magnitude(direction))
    );

    return {
      heading: heading + Cesium.Math.toRadians(100),
      pitch: 0,
      roll: 0,
    };
  }
  change(e, i) {
    this._height = e.height;
    console.log( e.speed );
    this._viewer.clock.multiplier = e.speed;
  }
  /**
   * 继续路径漫游
   */
  continueRoaming() {
    this._viewer.clock.shouldAnimate = true;
    !!this._following && (this._viewer.trackedEntity = this._trackEntity);
  }

  /**
   * 退出路径漫游
   * @param {Function} callback 退出时执行的回调函数
   */
  destroyRoaming(callback = () => {}) {
    this._viewer.clock.shouldAnimate = false;
    this._viewer.trackedEntity = null;
    // this._viewer.clock.onTick.removeEventListener(this._clockListen);
    this._viewer.clock.onTick.removeEventListener(this._onTickEvent);
    //   this._trackEntity && this._viewer.entities.remove(this._trackEntity)
    //修正系统时间
    const currentTime = Cesium.JulianDate.now(new Cesium.JulianDate());
    this.setJulianDateFactor(
      currentTime,
      Cesium.JulianDate.addHours(
        this._viewer.clock.currentTime,
        24,
        new Cesium.JulianDate()
      ),
      1.0,
      false
    );
    //注销事件
    this._viewer.clock.onStop.removeEventListener(this.doWhenComplete, this);
    console.log(
      `listener count=${this._viewer.clock.onStop.numberOfListeners}`
    );
    typeof callback === "function" && callback();
  }
}
